﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Novacode;
using System.Globalization;

using Word = Microsoft.Office.Interop.Word;
using Microsoft.Office.Interop.Word;
using System.Data;
using JasRibbonApplicatie.Model;

namespace JasRibbonApplicatie.Classes
{
    static class Formulieren
    {
        const string VOORLOPIG_TEMPLATE = "Templates/1 - voorlopig [Template].docx";
        const string DEFINITIEF_TEMPLATE = "Templates/2 - definitieve [Template].docx";
        const string NAAFHALING_TEMPLATE = "Templates/3 - na afhaling [Template].docx";
        const string NAINLEVERING_TEMPLATE = "Templates/4 - na inlevering [Template].docx";

        const string CULTURE_INFO = "nl-BE";

        private static AanvraagModel am = new AanvraagModel();

        public static string createVoorlopigFormulier(Aanvraag aanvraag, Model.Model model)
        {
            CultureInfo lang = new CultureInfo(CULTURE_INFO);
            DocX doc = DocX.Load(VOORLOPIG_TEMPLATE);

            Novacode.Table t = doc.Tables[3];
            Novacode.Table invoice_table = CreateAndInsertInvoiceTableAfter(t, ref doc, TableDesign.LightShadingAccent6, aanvraag, model);
            t.Remove();

            #region algemene gegevens
            doc.AddCustomProperty(new Novacode.CustomProperty("AanvraagID", aanvraag.aanvraag_id));
            doc.AddCustomProperty(new Novacode.CustomProperty("Vereniging", aanvraag.vereniging.vereniging));
            doc.AddCustomProperty(new Novacode.CustomProperty("VerantwNaamVoornaam", aanvraag.gebruiker.NaamVoornaam));
            doc.AddCustomProperty(new Novacode.CustomProperty("VerantwAdres", aanvraag.gebruiker.StraatNr));
            doc.AddCustomProperty(new Novacode.CustomProperty("VerantwWoonplaats", aanvraag.gebruiker.PostcodeGemeente));
            doc.AddCustomProperty(new Novacode.CustomProperty("VerantwGSM", aanvraag.gebruiker.gsm));

            doc.AddCustomProperty(new Novacode.CustomProperty("EvenementNaam", aanvraag.evenement.naam));
            doc.AddCustomProperty(new Novacode.CustomProperty("EvenementPlaats", aanvraag.evenement.plaats));
            doc.AddCustomProperty(new Novacode.CustomProperty("EvenementVan", aanvraag.evenement.start));
            doc.AddCustomProperty(new Novacode.CustomProperty("EvenementTot", aanvraag.evenement.einde));

            doc.AddCustomProperty(new Novacode.CustomProperty("Rekeninghouder", aanvraag.rekeninghouder));
            doc.AddCustomProperty(new Novacode.CustomProperty("RekeningNummer", aanvraag.rekeningnummer));

            doc.AddCustomProperty(new Novacode.CustomProperty("GeplandeAfhaling", aanvraag.geplande_afhaling.Value));
            doc.AddCustomProperty(new Novacode.CustomProperty("GeplandeInlevering", aanvraag.geplande_inlevering.Value));
            doc.AddCustomProperty(new Novacode.CustomProperty("OpmAfhaling", aanvraag.opmerking_afhaling));
            doc.AddCustomProperty(new Novacode.CustomProperty("OpmInlevering", aanvraag.opmerking_inlevering));

            doc.AddCustomProperty(new Novacode.CustomProperty("TotaalHuur", aanvraag.prijs.ToString("c", lang)));
            doc.AddCustomProperty(new Novacode.CustomProperty("TotaalWaarborg", aanvraag.waarborg.ToString("c", lang)));
            doc.AddCustomProperty(new Novacode.CustomProperty("TotaalPrijs", (aanvraag.prijs + aanvraag.waarborg).ToString("c", lang)));
            #endregion

            

            // Save this document as the users name followed by .docx
            string filename = "Formulieren/"+string.Format(@"{0}.docx", "voorlopig_" + aanvraag.aanvraag_id);
            try
            {
                doc.SaveAs(filename);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Formulieren.cs createVoorlopigFormulier exeption:" + ex.ToString());
                    
            }
            return filename;
        }
        public static string createDefinitiefFormulier(Aanvraag aanvraag, Model.Model model)
        {
            CultureInfo lang = new CultureInfo(CULTURE_INFO);
            DocX doc = DocX.Load(DEFINITIEF_TEMPLATE);

            Novacode.Table t = doc.Tables[3];
            Novacode.Table invoice_table = CreateAndInsertInvoiceTableAfter(t, ref doc, TableDesign.LightShadingAccent1, aanvraag, model);
            t.Remove();

            #region algemene gegevens
            doc.AddCustomProperty(new Novacode.CustomProperty("AanvraagID", aanvraag.aanvraag_id));
            doc.AddCustomProperty(new Novacode.CustomProperty("Vereniging", aanvraag.vereniging.vereniging));
            doc.AddCustomProperty(new Novacode.CustomProperty("VerantwNaamVoornaam", aanvraag.gebruiker.NaamVoornaam));
            doc.AddCustomProperty(new Novacode.CustomProperty("VerantwAdres", aanvraag.gebruiker.StraatNr));
            doc.AddCustomProperty(new Novacode.CustomProperty("VerantwWoonplaats", aanvraag.gebruiker.PostcodeGemeente));
            doc.AddCustomProperty(new Novacode.CustomProperty("VerantwGSM", aanvraag.gebruiker.gsm));

            doc.AddCustomProperty(new Novacode.CustomProperty("EvenementNaam", aanvraag.evenement.naam));
            doc.AddCustomProperty(new Novacode.CustomProperty("EvenementPlaats", aanvraag.evenement.plaats));
            doc.AddCustomProperty(new Novacode.CustomProperty("EvenementVan", aanvraag.evenement.start.ToString("dd/MM/yyyy HH:mm")));
            doc.AddCustomProperty(new Novacode.CustomProperty("EvenementTot", aanvraag.evenement.einde.ToString("dd/MM/yyyy HH:mm")));

            doc.AddCustomProperty(new Novacode.CustomProperty("Rekeninghouder", aanvraag.rekeninghouder));
            doc.AddCustomProperty(new Novacode.CustomProperty("RekeningNummer", aanvraag.rekeningnummer));

            doc.AddCustomProperty(new Novacode.CustomProperty("AfhalingMagazijnierNaam", (aanvraag.magazijnierAfhaling != null) ? aanvraag.magazijnierAfhaling.gebruiker.NaamVoornaam : ""));
            doc.AddCustomProperty(new Novacode.CustomProperty("AfhalingMagazijnierGSM", (aanvraag.magazijnierAfhaling != null) ? aanvraag.magazijnierAfhaling.gebruiker.gsm : ""));
            doc.AddCustomProperty(new Novacode.CustomProperty("InleveringMagazijnierNaam", (aanvraag.magazijnierInlevering!=null)? aanvraag.magazijnierInlevering.gebruiker.NaamVoornaam:""));
            doc.AddCustomProperty(new Novacode.CustomProperty("InleveringMagazijnierGSM", (aanvraag.magazijnierInlevering != null) ? aanvraag.magazijnierInlevering.gebruiker.gsm : ""));

            doc.AddCustomProperty(new Novacode.CustomProperty("GeplandeAfhaling", aanvraag.geplande_afhaling.Value.ToString("dd/MM/yyyy HH:mm")));
            doc.AddCustomProperty(new Novacode.CustomProperty("GeplandeInlevering", aanvraag.geplande_inlevering.Value.ToString("dd/MM/yyyy HH:mm")));
            doc.AddCustomProperty(new Novacode.CustomProperty("OpmAfhaling", aanvraag.opmerking_afhaling));
            doc.AddCustomProperty(new Novacode.CustomProperty("OpmInlevering", aanvraag.opmerking_inlevering));

            doc.AddCustomProperty(new Novacode.CustomProperty("TotaalHuur", aanvraag.prijs.ToString("c", lang)));
            doc.AddCustomProperty(new Novacode.CustomProperty("TotaalWaarborg", aanvraag.waarborg.ToString("c", lang)));
            doc.AddCustomProperty(new Novacode.CustomProperty("TotaalPrijs", (aanvraag.prijs + aanvraag.waarborg).ToString("c", lang)));
            #endregion



            // Save this document as the users name followed by .docx
            string filename = "Formulieren/" + string.Format(@"{0}.docx", "definitief_" + aanvraag.aanvraag_id);
            try
            {
                doc.SaveAs(filename);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Formulieren.cs createDefinitiefFormulier exeption:" + ex.ToString());
            }
            return filename;
        }
        public static string createMateriaalBuitenFormulier(Aanvraag aanvraag, Model.Model model)
        {
            CultureInfo lang = new CultureInfo(CULTURE_INFO);
            DocX doc = DocX.Load(NAAFHALING_TEMPLATE);

            Novacode.Table t = doc.Tables[3];
            Novacode.Table invoice_table = CreateAndInsertInvoiceTableAfter(t, ref doc, TableDesign.LightShadingAccent3, aanvraag, model);
            t.Remove();

            #region algemene gegevens
            doc.AddCustomProperty(new Novacode.CustomProperty("AanvraagID", aanvraag.aanvraag_id));
            doc.AddCustomProperty(new Novacode.CustomProperty("Vereniging", aanvraag.vereniging.vereniging));
            doc.AddCustomProperty(new Novacode.CustomProperty("VerantwNaamVoornaam", aanvraag.gebruiker.NaamVoornaam));
            doc.AddCustomProperty(new Novacode.CustomProperty("VerantwAdres", aanvraag.gebruiker.StraatNr));
            doc.AddCustomProperty(new Novacode.CustomProperty("VerantwWoonplaats", aanvraag.gebruiker.PostcodeGemeente));
            doc.AddCustomProperty(new Novacode.CustomProperty("VerantwGSM", aanvraag.gebruiker.gsm));

            doc.AddCustomProperty(new Novacode.CustomProperty("EvenementNaam", aanvraag.evenement.naam));
            doc.AddCustomProperty(new Novacode.CustomProperty("EvenementPlaats", aanvraag.evenement.plaats));
            doc.AddCustomProperty(new Novacode.CustomProperty("EvenementVan", aanvraag.evenement.start.ToString("dd/MM/yyyy HH:mm")));
            doc.AddCustomProperty(new Novacode.CustomProperty("EvenementTot", aanvraag.evenement.einde.ToString("dd/MM/yyyy HH:mm")));

            doc.AddCustomProperty(new Novacode.CustomProperty("Rekeninghouder", aanvraag.rekeninghouder));
            doc.AddCustomProperty(new Novacode.CustomProperty("RekeningNummer", aanvraag.rekeningnummer));

            doc.AddCustomProperty(new Novacode.CustomProperty("AfhalingMagazijnierNaam", (aanvraag.magazijnierAfhaling != null) ? aanvraag.magazijnierAfhaling.gebruiker.NaamVoornaam : ""));
            doc.AddCustomProperty(new Novacode.CustomProperty("AfhalingMagazijnierGSM", (aanvraag.magazijnierAfhaling != null) ? aanvraag.magazijnierAfhaling.gebruiker.gsm : ""));
            doc.AddCustomProperty(new Novacode.CustomProperty("InleveringMagazijnierNaam", (aanvraag.magazijnierInlevering != null) ? aanvraag.magazijnierInlevering.gebruiker.NaamVoornaam : ""));
            doc.AddCustomProperty(new Novacode.CustomProperty("InleveringMagazijnierGSM", (aanvraag.magazijnierInlevering != null) ? aanvraag.magazijnierInlevering.gebruiker.gsm : ""));

            doc.AddCustomProperty(new Novacode.CustomProperty("GeplandeAfhaling", aanvraag.geplande_afhaling.Value.ToString("dd/MM/yyyy HH:mm")));
            doc.AddCustomProperty(new Novacode.CustomProperty("GeplandeInlevering", aanvraag.geplande_inlevering.Value.ToString("dd/MM/yyyy HH:mm")));
            doc.AddCustomProperty(new Novacode.CustomProperty("OpmAfhaling", aanvraag.opmerking_afhaling));
            doc.AddCustomProperty(new Novacode.CustomProperty("OpmInlevering", aanvraag.opmerking_inlevering));

            doc.AddCustomProperty(new Novacode.CustomProperty("TotaalHuur", aanvraag.prijs.ToString("c", lang)));
            doc.AddCustomProperty(new Novacode.CustomProperty("TotaalWaarborg", aanvraag.waarborg.ToString("c", lang)));
            doc.AddCustomProperty(new Novacode.CustomProperty("TotaalPrijs", (aanvraag.prijs + aanvraag.waarborg).ToString("c", lang)));
            #endregion



            // Save this document as the users name followed by .docx
            string filename = "Formulieren/" + string.Format(@"{0}.docx", "naafhaling_" + aanvraag.aanvraag_id);
            try
            {
                doc.SaveAs(filename);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Formulieren.cs createMateriaalBuitenFormulier exeption:" + ex.ToString());
            }
            return filename;
        }
        public static string createOntleningAfgerondFormulier(Aanvraag aanvraag, Model.Model model)
        {
            return "URL van het gecreëerde formulier";
        }

        private static Novacode.Table CreateAndInsertInvoiceTableAfter(Novacode.Table t, ref DocX document, TableDesign td, Aanvraag aanvraag, Model.Model model)
        {
            CultureInfo lang = new CultureInfo(CULTURE_INFO);
            DataTable datatable = new DataTable();
            datatable.Columns.AddRange(new DataColumn[] { new DataColumn("Materiaal"), new DataColumn("Aantal"), new DataColumn("Prijs per stuk"), new DataColumn("Subtotaal"), new DataColumn("Periode"), new DataColumn("Totaal"), new DataColumn("Waarborg") });

            int[] betaaldagen =  am.GetBetaaldagen(aanvraag);
            string periode = ((betaaldagen[0] > 0) ? betaaldagen[0] + "w" : "") + ((betaaldagen[1] > 0) ? betaaldagen[1] + "d" : "");
            float totaalSubtotaal = 0;
            float totaalTotaal = 0;
            float totaalWaarborg = 0;

            foreach (MateriaalBestelling bestelling in aanvraag.materiaalbestelling)
            {
                string materiaal = bestelling.materiaaltype.naam;
                int aantal = bestelling.aantalGoedgekeurd;
                float prijsperstuk = bestelling.materiaaltype.dagprijs;
                float subtotaal = bestelling.aantalGoedgekeurd * bestelling.materiaaltype.dagprijs;
                float totaal = (betaaldagen[0] * 4 + betaaldagen[1]) * subtotaal;
                float waarborg = ((bestelling.aantalGoedgekeurd > 0) ? bestelling.materiaaltype.waarborg + (bestelling.aantalGoedgekeurd-1)*bestelling.materiaaltype.waarborgExtraStuks : 0);

                datatable.Rows.Add
                (
                    bestelling.materiaaltype.naam,
                    aantal,
                    prijsperstuk.ToString("c", lang),
                    subtotaal.ToString("c", lang),
                    periode,
                    totaal.ToString("c", lang),
                    waarborg.ToString("c", lang)
                );

                totaalSubtotaal += subtotaal;
                totaalTotaal += totaal;
                totaalWaarborg += waarborg;
            }
            
            
            /* 
             * The trick to replacing one Table with another,
             * is to insert the new Table after the old one, 
             * and then remove the old one.
             */

            Novacode.Table invoice_table = t.InsertTableAfterSelf(datatable.Rows.Count + 1, datatable.Columns.Count);
            invoice_table.Design = td;


            #region Table title
            Formatting table_title = new Formatting();
            table_title.Bold = true;
            table_title.Size = 8;
            table_title.FontFamily = (from f in System.Drawing.FontFamily.Families
                                      where f.GetName(0).Contains("Calibri")
                                      select f).First();

            //MATERIAAL	Aantal	Prijs per stuk	Subtotaal	Periode	Totaal	Waarborg
            invoice_table.Rows[0].Cells[0].Paragraphs[0].InsertText("Materiaal", false, table_title);
            invoice_table.Rows[0].Cells[0].Paragraphs[0].Alignment = Alignment.center;
            invoice_table.Rows[0].Cells[1].Paragraphs[0].InsertText("Aantal", false, table_title);
            invoice_table.Rows[0].Cells[1].Paragraphs[0].Alignment = Alignment.center;
            invoice_table.Rows[0].Cells[2].Paragraphs[0].InsertText("Prijs per stuk", false, table_title);
            invoice_table.Rows[0].Cells[2].Paragraphs[0].Alignment = Alignment.center;
            invoice_table.Rows[0].Cells[3].Paragraphs[0].InsertText("Subtotaal", false, table_title);
            invoice_table.Rows[0].Cells[3].Paragraphs[0].Alignment = Alignment.center;
            invoice_table.Rows[0].Cells[4].Paragraphs[0].InsertText("Periode", false, table_title);
            invoice_table.Rows[0].Cells[4].Paragraphs[0].Alignment = Alignment.center;
            invoice_table.Rows[0].Cells[5].Paragraphs[0].InsertText("Totaal", false, table_title);
            invoice_table.Rows[0].Cells[5].Paragraphs[0].Alignment = Alignment.center;
            invoice_table.Rows[0].Cells[6].Paragraphs[0].InsertText("Waarborg", false, table_title);
            invoice_table.Rows[0].Cells[6].Paragraphs[0].Alignment = Alignment.center;

            #endregion
            Formatting table_text = new Formatting();
            table_text.Bold = false;
            table_text.Size = table_title.Size;
            table_text.FontFamily = table_title.FontFamily;

            // Loop through the rows in the Table and insert data from the data source.
            for (int row = 1; row < invoice_table.RowCount; row++)
            {
                for (int cell = 0; cell < invoice_table.Rows[row].Cells.Count; cell++)
                {
                    Novacode.Paragraph cell_paragraph = invoice_table.Rows[row].Cells[cell].Paragraphs[0];
                    if (cell == 0)
                        cell_paragraph.InsertText(datatable.Rows[row - 1].ItemArray[cell].ToString(), false, table_title);
                    else
                        cell_paragraph.InsertText(datatable.Rows[row - 1].ItemArray[cell].ToString(), false, table_text);
                }
            }

            // We want to fill in the total by suming the values from the amount coloumn.
            Novacode.Row total = invoice_table.InsertRow();
            total.Cells[0].Paragraphs[0].InsertText("Totaal:", false, table_title);
            total.Cells[1].Paragraphs[0].InsertText("&nbsp;", false, table_text);
            total.Cells[2].Paragraphs[0].InsertText("&nbsp;", false, table_text);
            total.Cells[3].Paragraphs[0].InsertText(totaalSubtotaal.ToString("c",lang), false, table_text);
            total.Cells[4].Paragraphs[0].InsertText(periode, false, table_text);
            total.Cells[5].Paragraphs[0].InsertText(totaalTotaal.ToString("c",lang), false, table_title);
            total.Cells[6].Paragraphs[0].InsertText(totaalWaarborg.ToString("c", lang), false, table_title);

            aanvraag.waarborg = totaalWaarborg;
            aanvraag.prijs = totaalTotaal;

            Novacode.Border orangeBorder = new Novacode.Border()
            {
                Color = System.Drawing.Color.FromName("#9BBB59"),
                Size = Novacode.BorderSize.four
            };
            foreach (Novacode.Cell c in total.Cells) c.SetBorder(TableCellBorderType.Top, orangeBorder);


            // Let the tables coloumns expand to fit its contents.
            invoice_table.AutoFit = AutoFit.Contents;

            // Center the Table
            invoice_table.Alignment = Alignment.left;

            // Return the invloce table now that it has been created.
            return invoice_table;
        }


        public static void docxToPdf(string input, string output, WdSaveFormat format = WdSaveFormat.wdFormatPDF)
        {
            // Create an instance of Word.exe
            Word._Application oWord = new Word.Application();

            // Make this instance of word invisible (Can still see it in the taskmgr).
            oWord.Visible = false;

            // Interop requires objects.
            object oMissing = System.Reflection.Missing.Value;
            object isVisible = true;
            object readOnly = false;
            object oInput = input;
            object oOutput = output;
            object oFormat = format;

            // Load a document into our instance of word.exe
            Word._Document oDoc = oWord.Documents.Open(ref oInput, ref oMissing, ref readOnly, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref isVisible, ref oMissing, ref oMissing, ref oMissing, ref oMissing);

            // Make this document the active document.
            oDoc.Activate();

            // Save this document in Word 2003 format.
            oDoc.SaveAs(ref oOutput, ref oFormat, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing);

            // Always close Word.exe.
            oWord.Quit(ref oMissing, ref oMissing, ref oMissing);
        }
        
    }
}
